#include "TwOgreRealVariable.h"

#include <sstream>

#include "TwOgreWindow.h"
#include "TwOgreWindowManager.h"

namespace TwOgre{
	RealVariable::RealVariable(Window *parent, const Ogre::String& name, bool readOnly, const Ogre::String& label, 
		Ogre::Real value, const Ogre::String& groupName, const Ogre::String& help) :
		Variable(parent, name, TW_TYPE_DOUBLE), mValue(value)
	{
		mDoubleValue = mValue;
		if(readOnly)
		{
			TwAddVarRO(mParent->getTweakBar(), mName.c_str(), TW_TYPE_DOUBLE, &mDoubleValue, "");
		}
		else
		{
			TwAddVarRW(mParent->getTweakBar(), mName.c_str(), TW_TYPE_DOUBLE, &mDoubleValue, "");
		}

		if(label.compare("") != 0)
		{
			setLabel(label);
		}
		if(groupName.compare("") != 0)
		{
			setGroup(groupName);
		}
		if(help.compare("") != 0)
		{
			setHelp(help);
		}
	}

	RealVariable::RealVariable(RealParams& params) :
        Variable(params.parent_, params.name_, params.type_), mValue(params.value_)
    {
		mDoubleValue = mValue;
        if((params.getCB_ != NULL) && (params.setCB_ != NULL) && (params.data_ != NULL))
        {
            TwAddVarCB(mParent->getTweakBar(), mName.c_str(), params.type_, params.setCB_, params.getCB_, params.data_, "");
        }
        else
        {
		    if(params.readOnly_)
		    {
                TwAddVarRO(mParent->getTweakBar(), mName.c_str(), params.type_, &mDoubleValue, "");
		    }
		    else
		    {
                TwAddVarRW(mParent->getTweakBar(), mName.c_str(), params.type_, &mDoubleValue, "");
		    }
        }
		
        if(params.label_.compare("") != 0)
		{
			setLabel(params.label_);
		}
		if(params.group_.compare("") != 0)
		{
			setGroup(params.group_);
		}
		if(params.help_.compare("") != 0)
		{
			setHelp(params.help_);
		}
        
        setLimits(params.min_, params.max_, params.step_);

        setPrecision(params.precision_);

        if((params.shortcutIncr_.compare("") != 0) || (params.shortcutDecr_.compare("") != 0))
		{
            setShortcut(params.shortcutIncr_, params.shortcutDecr_);
        }
    }
	
    RealVariable::~RealVariable()
	{
		TwRemoveVar(mParent->getTweakBar(), mName.c_str());
	}

	Ogre::Real RealVariable::getRealValue() const
	{
		mValue = static_cast<Ogre::Real>(mDoubleValue);
		return mValue;
	}

	void RealVariable::setRealValue(Ogre::Real value)
	{
		mValue = value;
		mDoubleValue = mValue;
	}

	void RealVariable::setPrecision(int precision)
	{
		std::stringstream ss;
		ss << " '" << mParent->getName() << "'/'" <<  mName << "' Precision=" << precision;
		TwDefine(ss.str().c_str());
	}

	void RealVariable::setLimits(Ogre::Real min, Ogre::Real max, Ogre::Real step)
	{
		// At least the min must be set
		std::stringstream ss;
		ss << " '" << mParent->getName() << "'/'" <<  mName << "' Min=" << min << " ";

		// If the user didn't specify a max, skip it
		if(max != REAL_INFINITY)
		{
			ss << " Max=" << max << " ";
		}
		// If the user didn't specify a step, skip it
		if(step != REAL_INFINITY)
		{
			ss << " Step=" << step << " ";
		}

		TwDefine(ss.str().c_str());
	}

	void RealVariable::setShortcut(const Ogre::String& increment, const Ogre::String& decrement)
	{
		std::stringstream ss;
		ss << " '" << mParent->getName() << "'/'" <<  mName 
		   << "' KeyIncr='" << increment
		   << "' KeyDecr='" << decrement << "' ";

		TwDefine(ss.str().c_str());
	}
}; // End Namespace
